using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Design;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using OpenComposite.EII.Repository;
using System.Collections.ObjectModel;

namespace OpenComposite.EII.RepositoryUIs
{
	[ToolboxItem(true)]
	[ToolboxBitmap(typeof(TreeView))]
	public class BusinessObjectsTreeView : TreeView
	{
		#region Initialization
		public BusinessObjectsTreeView()
		{
			_listBObjs = new NamedBusinessObjectCollection();
			_visibledatatypes = null;

			InitializeComponent();

			this.PathSeparator = ".";
			this.ImageList = imgList;
		}
		#endregion

		#region Public Members

		#region Constants
		public const string BusinessObjectImageKey = "bobject";
		public const string BusinessObjectListImageKey = "list_of_bobjects";
		public const string NounImageKey = "noun";
		#endregion

		#region Properties
		public string VisibleDataTypes
		{
			get { return _visibledatatypes; }
			set
			{
				if ( _visibledatatypes != value ) {
					_visibledatatypes = value;
					fillTree();
				}
			}
		}
		public ReadOnlyCollection<BusinessObject> BusinessObjects
		{
			get { return new ReadOnlyCollection<BusinessObject>(_listBObjs.BusinessObjects); }
		}
		#endregion

		#region Methods
		public void SetBusinessObjects(NamedBusinessObjectCollection listBusinessObjects)
		{
			_listBObjs.Clear();
			_listBObjs.AddRange(listBusinessObjects);
			fillTree();
		}

		#endregion

		#endregion

		#region Protected Members

		#region Methods
		#endregion

		#endregion

		#region Private Members

		#region Variables
		private NamedBusinessObjectCollection _listBObjs;
		private string _visibledatatypes;
		private ImageList imgList;
		#endregion

		#region Methods
		private void fillTree()
		{
			this.BeginUpdate();
			try {
				this.Nodes.Clear();
				foreach ( var item in _listBObjs ) {
					createBObjectTree(item, null);
				}
			} finally {
				this.EndUpdate();
			}
		}
		private void createBObjectTree(NamedBusinessObject bobjCurrent, TreeNode tnCurrent)
		{
			BusinessObject bobj = bobjCurrent.BusinessObject;

			// Create TreeNode for the current BusinessObject
			TreeNode tnBO = new TreeNode(bobjCurrent.Name);
			tnBO.ImageKey = BusinessObjectImageKey;
			tnBO.SelectedImageKey = BusinessObjectImageKey;
			if ( tnCurrent == null )
				this.Nodes.Add(tnBO);
			else
				tnCurrent.Nodes.Add(tnBO);

			if ( bobj.WorkflowField != null && bobj.WorkflowField.BusinessObject != null )
				bobj = bobj.WorkflowField.BusinessObject;

			// Create TreeNodes for the Fields of current BusinessObject
			foreach ( BusinessObjectField field in bobj.BusinessObjectFields ) {
				if ( field.IsReference ) {
					BusinessObject boChild = field.BusinessObject;
					// add referenced BusinessObject/List
					if ( boChild != null ) {
						if ( boChild.Name == field.Name ) {
							createBObjectTree(boChild, tnBO);
						} else {
							TreeNode tnList = new TreeNode(field.Name);
							tnList.ImageKey = tnList.SelectedImageKey = BusinessObjectListImageKey;
							tnBO.Nodes.Add(tnList);
							createBObjectTree(boChild, tnList);
						}
					}
				} else {
					Noun noun = field.Noun;
					if ( noun != null &&
						 ( string.IsNullOrEmpty(_visibledatatypes) ||
						   _visibledatatypes.ToLower().Contains(noun.DataType.ToLower()) ) ) {
						TreeNode tnField = new TreeNode(noun.Name);
						tnField.ImageKey = tnField.SelectedImageKey = NounImageKey;
						tnBO.Nodes.Add(tnField);
					}
				}
			}
			if ( tnCurrent == null )
				tnBO.Expand();
		}

		private void createBObjectTree(BusinessObject bobjCurrent, TreeNode tnCurrent)
		{
			BusinessObject bobj = bobjCurrent;

			// Create TreeNode for the current BusinessObject
			TreeNode tnBO = new TreeNode(bobjCurrent.Name);
			tnBO.ImageKey = BusinessObjectImageKey;
			tnBO.SelectedImageKey = BusinessObjectImageKey;
			if ( tnCurrent == null )
				this.Nodes.Add(tnBO);
			else
				tnCurrent.Nodes.Add(tnBO);

			if ( bobj.WorkflowField != null && bobj.WorkflowField.BusinessObject != null )
				bobj = bobj.WorkflowField.BusinessObject;

			// Create TreeNodes for the Fields of current BusinessObject
			foreach ( BusinessObjectField field in bobj.BusinessObjectFields ) {
				if ( field.IsReference ) {
					BusinessObject boChild = field.BusinessObject;
					// add referenced BusinessObject/List
					if ( boChild != null ) {
						if ( boChild.Name == field.Name ) {
							createBObjectTree(boChild, tnBO);
						} else {
							TreeNode tnList = new TreeNode(field.Name);
							tnList.ImageKey = tnList.SelectedImageKey = BusinessObjectListImageKey;
							tnBO.Nodes.Add(tnList);
							createBObjectTree(boChild, tnList);
						}
					}
				} else {
					Noun noun = field.Noun;
					if ( noun != null &&
						 ( string.IsNullOrEmpty(_visibledatatypes) ||
						   _visibledatatypes.ToLower().Contains(noun.DataType.ToLower()) ) ) {
						TreeNode tnField = new TreeNode(noun.Name);
						tnField.ImageKey = tnField.SelectedImageKey = NounImageKey;
						tnBO.Nodes.Add(tnField);
					}
				}
			}
			if ( tnCurrent == null )
				tnBO.Expand();
		}
		#endregion

		#endregion

		#region Generated Code

		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BusinessObjectsTreeView));
			this.imgList = new System.Windows.Forms.ImageList(this.components);
			this.SuspendLayout();
			// 
			// imgList
			// 
			this.imgList.ImageStream = ( (System.Windows.Forms.ImageListStreamer)( resources.GetObject("imgList.ImageStream") ) );
			this.imgList.TransparentColor = System.Drawing.Color.Fuchsia;
			this.imgList.Images.SetKeyName(0, "bobject");
			this.imgList.Images.SetKeyName(1, "noun");
			this.imgList.Images.SetKeyName(2, "list_of_bobjects");
			// 
			// BusinessObjectsTreeView
			// 
			this.LineColor = System.Drawing.Color.Black;
			this.ResumeLayout(false);

		}

		private System.ComponentModel.IContainer components;

		#endregion

	}
}
